/*
 * @Author: shawnxiao
 * @Date: 2021-10-25 17:56:42
 * @LastEditTime: 2021-11-12 15:20:57
 * @FilePath: /gatt-react/src/index/views/Home/components/GattDrag/components/GattDate/index.tsx
 */
import React, {useEffect, useState, useRef} from 'react'
import { Transition } from 'react-transition-group'
import FirstRow from './components/FirstRow'
import SecondRow from './components/SecondRow'
import LineAll from './components/LineAll'
import './index.less'
import { DownOutlined } from '@ant-design/icons'
import { Menu, Dropdown } from 'antd'
import {isLeapYear} from '@/common/utils'
import useDeepCompareEffect from '@/common/utils/useDeepCompareEffect'

import {computedWithTime, handleMonthDay, computedLeft } from './utils'
import {gattItemParams, gattItemBaseParams} from '../../index'

export interface currentDaySizeType {
  label:string
  mode:string
  value:number
}
interface PropsGattMain{
  rightLineX:number
  widthRight:number
  dataArr:gattItemParams[]
  setDataArr:any
  fieldsAttr:any
  startTime:number
  endTime:number
}
export interface currentLineDayType{
  start: number
  end: number
}
interface currentProjectMsgType{
  top:number
  left:number
  name?:string
  startTime?:string
  endTime?:string
  per?:string|number
}

const dayModeSize = [
  {
    label: '按天',
    value: 40,
    mode: 'day'
  },
  {
    label: '按周',
    value: 24,
    mode: 'week'
  },
  {
    label: '月度',
    value: 12,
    mode: 'month'
  },
  {
    label: '季度',
    value: 6,
    mode: 'quarter'
  },
  {
    label: '半年',
    value: 3,
    mode: 'halfYear'
  }
]
const monthArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

function GattMain(props:PropsGattMain) {
  const gattMainRef:any = useRef(null)
  const gattMainContRef:any = useRef(null)
  const {dataArr, setDataArr, fieldsAttr, rightLineX, widthRight, startTime, endTime} = props
  const [lineBgHeight, setLineBgHeight] = useState<number>(0)
  const [toolTipTop, setToolTipTop] = useState<number>(82)
  // 当前的时间大小
  const [currentDaySize, setCurrentDaySize] = useState<currentDaySizeType>({
    label: '按天',
    value: 40,
    mode: 'day'
  })
  const [scrollXSize, setScrollXSize] = useState<number>(0)
  const [showFixedTopMonth, setShowFixedTopMonth] = useState<boolean>(false)
  const [fixedTopMonth, setFixedTopMonth] = useState<string>('')
  const [currentYear] = useState<number>(new Date().getFullYear()) // 当前年份
  const [currentMonth] = useState<number>(new Date().getMonth() + 1) // 当前月份
  const [currentDay] = useState<number>(new Date().getDate()) // 当前日
  const [allDays, setAllDays] = useState<any[]>([]) // 最近三年与最小年份至最大年份并集内的所有年月日
  const [days, setDays] = useState<any[]>([]) // 所有的天数
  const [translateX, setTranslateX] = useState<number>(0) // 日期偏移距离
  const [isShowMsg, setIsShowMsg] = useState<boolean>(false)
  const [currentProjectMsg, setCurrentProjectMsg] = useState<currentProjectMsgType[]>([])
  // const [fieldsProjectMsg, setFieldsProjectMsg] = useState<any[]>([])
  // 当前hover的项目起止时间
  const [currentLineDay, setCurrentLineDay] = useState<currentLineDayType>({
    start: 0,
    end: 0
  })
  useEffect(() => {
    const height = parseFloat(window.getComputedStyle(
      document.getElementsByClassName('gatt-main-wrap-cont')[0]
    ).height)
    setLineBgHeight(height)
  }, [])

  // 依据时间计算left，width top设置list
  useDeepCompareEffect(() => {
    const arr:gattItemParams[] = []
    const temShow = dataArr.filter((item:any) => item?.isShow)
    dataArr.forEach((item:gattItemBaseParams) => {
      const obj:any = {...item}
      let startLeft = 0; let endLeft = 0
      if (item.startTime) {
        // 依据开始时间设置left
        startLeft = computedLeft({startTimeStamp: item.startTime, currentYear, currentDaySizeVal: currentDaySize.value})
        obj.left = startLeft
      }
      if (item.endTime) {
        // 依据结束时间设置width
        endLeft = computedLeft({startTimeStamp: item.endTime, currentYear, currentDaySizeVal: currentDaySize.value})
        obj.widthMe = endLeft - startLeft
        obj.widthChild = endLeft - startLeft
      }
      // 依据索引设置top
      const topStep = 40
      const index = temShow.findIndex((tem:any) => tem.id === item.id)
      obj.top = topStep * index + 12
      arr.push(obj)
    })
    setDataArr(arr)
  }, [dataArr, currentYear, currentDaySize.value])

  useEffect(() => {
    // 计算浮窗top
    const offsetTop:any = document.getElementById('gatt-box-root-right') ? document.getElementById('gatt-box-root-right')?.offsetTop : 0
    setToolTipTop((offsetTop + 43) as number)
    gattMainRef.current.addEventListener('scroll', handleScroll)
    return () => {
      gattMainRef.current.removeEventListener('scroll', handleScroll)
      document.onmousemove = document.onmouseup = null
    }
  }, [])
  // 横向滚动和更换日期模式计算时间
  useEffect(() => {
    setShowFixedTopMonth(scrollXSize > 62)
    // 防抖
    let timeOut:any = null // 初始化空定时器
    clearTimeout( timeOut ) // 频繁操作，一直清空先前的定时器
    timeOut = setTimeout( () => { // 只执行最后一次事件
      // 根据横向滚动的距离计算时间
      const time = '' + computedWithTime({width: scrollXSize, time: 'YD', startTime, currentYear, currentDaySize})
      setFixedTopMonth(time)
    }, 100 )
  }, [scrollXSize, startTime, currentYear, currentDaySize])
  // 计算allDays
  useEffect(() => {
    const startTimeYear = new Date(startTime).getFullYear()
    const endTimeYear = new Date(endTime).getFullYear()
    const tmp = [startTimeYear, endTimeYear, currentYear - 1, currentYear + 1]
    // 获取到最近三年与最小年份至最大年份并集内的所有年月日
    const min = Math.min.apply(null, tmp)
    const max = Math.max.apply(null, tmp)
    let obj:any = {}
    const arr:number[] = []
    const tmpAllDays:any[] = []
    for (let i = min; i <= max; i++) {
      arr.push(i)
    }
    arr.forEach(item => {
      obj.year = item
      obj.days = isLeapYear(item) ? 365 : 366
      tmpAllDays.push(obj)
      obj = {}
    })
    // 根据年份天数创建月份及该月份下的天数数组
    tmpAllDays.forEach(item => {
      item.month = handleMonthDay(item.days, item.year, monthArr)
    })
    tmpAllDays.forEach(element => {
      if (element.year === currentYear) {
        element.month[0][currentMonth].dayArr.forEach((k:any) => {
          if (k.date === currentDay) {
            k.today = true
          }
        })
      }
    })
    setAllDays(tmpAllDays)
  }, [startTime, endTime, currentYear, currentMonth, currentDay])
  // 计算days
  useEffect(() => {
    let arrTmp:any[] = []
    let arr:any[] = []
    allDays.forEach((element:any) => {
      arrTmp = arrTmp.concat(element.month)
    })
    arrTmp.forEach((item:any) => {
      for (const j in item) {
        arr = arr.concat(item[j].dayArr)
      }
    })
    arr.forEach((item, index) => {
      item.width = (index + 1) * currentDaySize.value
    })
    setDays(arr)
  }, [allDays])

  const handleScroll = () => {
    const scrollX = gattMainRef.current.scrollLeft
    const scrollY = gattMainRef.current.scrollTop
    setTranslateX(scrollX)
    setScrollXSize(scrollX)
    const r = document.getElementById('treeTableBox')
    if (r){
      const c = r.querySelector('.ant-table-body')
      if (c){
        c.scrollTop = scrollY
      }
    }
  }

  // 回到今天
  const handleGoToday = () => {
    const innerWidth = gattMainRef.current.clientWidth || window.innerWidth
    const s =
    Math.round(innerWidth / currentDaySize.value / 2) * currentDaySize.value - rightLineX
  const width =
    (Math.floor(
      new Date(
        `${currentYear}/${currentMonth}/${currentDay}`
      ).getTime() - new Date(`${currentYear - 1}/01/01`).getTime()
    ) / (1000 * 60 * 60 * 24)) * currentDaySize.value - s
    gattMainRef.current.scrollTo({
      top: 0,
      left: width,
      behavior: 'smooth'
    })
  }
  // 更改daySize
  const handleSetDaySize = (item:currentDaySizeType) => {
    setCurrentDaySize({...item})
    days.forEach((item:any, index:number) => {
      item.width = (index + 1) * item.value
    })
    handleScroll()
    // if (currentRow) {
    //   const rs = computedList.find(o => {
    //     return o.id === currentRow.id
    //   })
    //   window.scrollTo(rs.left - 100, 0)
    // }
    // element.scrollTo({
    //   top: 100,
    //   left: 100,
    //   behavior: 'smooth'
    // })
  }

  const menu = () => {
    return (<Menu>
      {
        dayModeSize.map((daySize:currentDaySizeType) => {
          return (
            <Menu.Item key={daySize.value} onClick={handleSetDaySize.bind(null, daySize)}>
              <span style={{textAlign: 'center', display: 'inline-block', width: '100%'}}>{daySize.label}</span>
            </Menu.Item>
          )
        })
      }
    </Menu>)
  }
  const getMainDomRefPx = () => {
    const w = gattMainRef?.current?.clientWidth
    const h = gattMainRef?.current?.clientHeight
    return {w, h, dom: gattMainRef}
  }
  return (
    // 甘特主题内容
    <div className="gatt-main">
      {/* 顶部固定显示的提示年月 */}
      {
        showFixedTopMonth ? <div className="topMonth">{fixedTopMonth}</div> : null
      }
      {/* 除第一行以外的容器 */}
      <div className="gatt-main-wrap">
        <div className="gatt-main-wrap-date" style={{transform: `translate3d(${-translateX}px, 0px,0px)`, WebkitTransform: `translate3d(${-translateX}px, 0px,0px)`, OTransform: `translate3d(${-translateX}px, 0px,0px)`}}>
          {/* 头部第一行，时间范围内所有年份一行排列 */}
          <FirstRow currentDaySize={currentDaySize} allDays={allDays}/>
          {/* 头部第二行 */}
          <SecondRow currentDaySize={currentDaySize} allDays={allDays} days={days} lineBgHeight={lineBgHeight} currentLineDay={currentLineDay}/>
        </div>
        {/* 内容区域容器 */}
        <div className="gatt-main-wrap-cont" ref={gattMainRef}>
          <div
            className="gatt-main-wrap-cont-c"
            ref={gattMainContRef}
            style={{width: `${days.length * currentDaySize.value}px`, height: `${dataArr.filter((item:any) => item?.isShow).length * 40}px`}}>
            <LineAll list={dataArr} fieldsAttr={fieldsAttr} setCurrentLineDay={setCurrentLineDay} rightLineX={rightLineX} currentDaySize={currentDaySize} setDataArr={setDataArr} startTime={startTime} currentYear={currentYear} days={days} setIsShowMsg={setIsShowMsg} setCurrentProjectMsg={setCurrentProjectMsg} getMainDomRefPx={getMainDomRefPx}></LineAll>
            {/* 时间模式选择 */}
            <div
              className="gatt-main-wrap-cont-toolTip"
              style={{left: `${widthRight + rightLineX + 2 - 175}px`, top: `${toolTipTop}px`}}
            >
              <Dropdown overlay={menu} placement="bottomCenter" arrow>
                <div className="base drop-type">
                  <span className="type">{currentDaySize.label}</span>
                  <DownOutlined />
                </div>
              </Dropdown>
              <div onClick={handleGoToday} className="today base" >今天</div>
            </div>
            {
              isShowMsg && currentProjectMsg.length ? <Transition in={isShowMsg} timeout={500}>
                <div
                  className="projectMsg"
                  style={{
                    left: currentProjectMsg[0].left + 'px',
                    top: currentProjectMsg[0].top + 'px'
                  }}
                >
                  {
                    currentProjectMsg.map((item:any, index:number) => (
                      <div className="lineMsg" key={`${item.key}-${index}`}>
                        {
                          item.key.includes('name') ? (
                            <span className="projectName">{item.value}</span>
                          ) : (
                            <>
                            <span className="title">{item.label}</span>
                            <span>{item.value}</span>
                            </>
                          )
                        }
                      </div>
                    ))
                  }
                </div>
              </Transition> : null
            }
          </div>
        </div>
      </div>
    </div>
  )
}

export default GattMain
